'use strict';
/**
 * author：小小游 --- allen
 * date：2018.02.05
 * lastUpdateDate：2018.02.05
 * description：Generator函数与yield语句的使用
 */
/**
  * 这是一个generator函数，内部它实现了Iterator接口
  * generator函数可以配合yield语句一起执行，如果没有yield语句，
  * 那么当调用next()方法的时候，就会执行完整个generator函数
  * 如果有了yield语句，它会把generator函数内部分成几段去执行，
  * 那么每一个断点是通过yield语句来暂停的
  * yield语句hereturn语句的区别就在于：yield语句可以返回多个值，
  * 而return语句每次只能返回一个值
  */
/**
 * 利用generator函数和promise来让异步这种逻辑关系用同步的方式表达出来
 * 我们知道同步的语句很好写，从上至下的执行，而在Javascript中，异步通常
 * 是通过回调的方式来实现，而这种回调的方式并不优雅，下面直接上例子，如下：
 */

const co = require('co');

// promise函数
function asyncFunc (name) {
    return new Promise ((resolve, reject) => {
        // 模拟异步执行
        setTimeout(() => {
            resolve (`my name is ${name}`);
        }, 200)
    });
}

// 做一个普通的加法函数
function sum (a, b) {
    return new Promise ((resolve, reject) => {
        setTimeout (() => {
            resolve (a + b);
        });
    });
}

// 下面使用Promise的写法来做下这个执行效果
// 从下面的代码可以看出使用generator会比promise更自然些
// function fn (name) {
//     sum (3, 5)
//         .then ((num) => {
//             if (num > 6) {
//                 asyncFunc (name)
//                     .then ((val) => {
//                         console.log(val);
//                     }, (error) => {
//                         console.log(`${error}`);
//                     });
//             } else {
//                 console.log('error!');
//             }
//         }, (error) => {
//             console.log(`${error}`);
//         });
// }

// generator函数
// 那么这种异步的写法就可以通过同步语法糖的方式来编写
function * fn (name) {
    // let name = yield asyncFunc('allen');
    // console.log(name);
    let sumResult = yield sum (3, 5);
    // result：8
    console.log(sumResult);
    if (sumResult > 6 ) {
        // result：my name is xiaoxiaoyou
        console.log(yield asyncFunc (name));
    } else {
        console.log('error!');
    }
}

// https://github.com/tj/co开发的吊炸天Generator执行器函数
let fnx = co.wrap(fn);
fnx ('xiaoyuyu');

/**
 * print result：{ value: Promise { <pending> }, done: false } start
 */
// var iterator = fn ();
// console.log(iterator.next());
/**
 * print result：{ value: Promise { <pending> }, done: false } end
 */

// 执行generator的函数，gf就是执行generator对象返回的指针对象
// let gf = fn ('xiaoxiaoyou');
// function executedFunc (gf, value) {
//     let iterator = gf.next(value);
//     // done为false才继续往下遍历
//     if (!iterator.done) {
//         // 判断是否为Promise的实例对象
//         // 串行化处理下
//         if (iterator.value instanceof Promise) {
//             iterator.value
//                 .then ((successVal) => {
//                     executedFunc (gf, successVal);
//                 }, (failVal) => {
//                     console.log(`${failVal}`);
//                 });
//         } else {
//             executedFunc (gf, iterator.value);
//         }
//     }
// }
//
// // 执行，看看效果，哈哈！
// executedFunc (gf);
